#include "headfile.h"

/*********************************************************************
 iic控制时序专用延时函数,两个;对应11.0592MHZ晶振4-5um，刚好符合iic对时序列要求
 ********************************************************************/
void delay_iic()
{
    ;
    ;
}

/**********************************************************************
 iic初始化函数
 ***********************************************************************/
sbit scl = P2 ^ 1;
sbit sda = P2 ^ 0;
void IIC_init()
{
    sda = 1;
    delay_iic();
    scl = 1;
    delay_iic();
}

/**********************************************************************
 iic发送起始信号
 ***********************************************************************/
void iic_start()
{
    sda = 1;
    delay_iic();
    scl = 1; //SCL,SDA点平都拉高
    delay_iic();
    sda = 0;
    delay_iic();
}

/**********************************************************************
 iic发送终止信号
 ***********************************************************************/
void iic_end()
{
    sda = 0;
    delay_iic();
    scl = 1;
    delay_iic();
    sda = 1;
    delay_iic();
}

/**********************************************************************
应答信号
 ***********************************************************************/
void iic_respons()
{
    uint8 i = 0;
    scl = 1;
    delay_iic();
    while ((sda == 1) && i < 255)
        i++; //主机判断sda信号线，低电平为应答。该句为延时时间内，强制默认从机应答，防止程序卡死。
    scl = 0;
    delay_iic();
}

/**********************************************************************
iic写一个字节
 ***********************************************************************/
void iic_w_byte(uint8 data_)
{
    uint8 i, cy;
    cy = data_;
    for (i = 0; i < 8; i++)
    {
        cy = cy << 1; //移位，将最高位移给CY
        scl = 0;
        delay_iic();
        sda = CY;
        delay_iic();
        scl = 1;
        delay_iic();
    }
    scl = 0; //拉低SCL
    delay_iic();
    sda = 1; //释放sda总线，写完一个字节等待应答信号，如果应答成功，sda被从机设为0
    delay_iic();
}

/**********************************************************************
iic读一个字节
 ***********************************************************************/
uint8 iic_r_byte()
{
    uint8 i, k = 0;
    scl = 0;
    delay_iic();
    sda = 1;
    delay_iic();
    for (i = 0; i < 8; i++)
    {
        scl = 1;
        delay_iic();
        k = (k << 1) | sda; //此时sda值由从机发送
        scl = 0;
        delay_iic();
    }
    return k;
}

/**********************************************************************
 iic发送1个字节到指定地址
 **********************************************************************/
void iic_sent_add(uint8 dev_add, uint8 reg, uint8 data_)
{
    iic_start();
    iic_w_byte(dev_add); //a是固件地址，对于EEPROM来说固定；0为三位可编程地址和末尾 0：写操作的
    iic_respons();
    iic_w_byte(reg);
    iic_respons();
    iic_w_byte(data_);
    iic_respons();
    iic_end();
}

/**********************************************************************
 iic从指定地址读1个字节
 **********************************************************************/
uint8 iic_read_add(uint8 dev_add, uint8 reg)
{
    uint8 data_;
    iic_start();
    iic_w_byte(dev_add | 0x00); //对应位置写操作
    iic_respons();
    iic_w_byte(reg);
    iic_respons();

    iic_start();
    iic_w_byte(dev_add | 0x01); //读操作
    iic_respons();
    data_ = iic_r_byte();
    iic_end();
    return data_;
}

/**********************************************************************
MPU6050初始化
前提是IIC初始化成功
 **********************************************************************/
void mpu6050_init()
{
    iic_sent_add(MPU6050_DEV_ADDR, PWR_MGMT_1, 0x00);   //解除休眠状态
    iic_sent_add(MPU6050_DEV_ADDR, SMPLRT_DIV, 0x01);   //125HZ采样率 1000/Hz-1（0x00：1000hz；0x01:500hz;0x03:225hz;0x07:125hz;0x13=50hz）
    iic_sent_add(MPU6050_DEV_ADDR, CONFIG, 0x01);       //低通滤波器
    iic_sent_add(MPU6050_DEV_ADDR, GYRO_CONFIG, 0x18);  //陀螺仪范围0x00=250dps;0x08=500dps;0x10=1000dps;0x18=2000dps
    iic_sent_add(MPU6050_DEV_ADDR, ACCEL_CONFIG, 0x10); //加速度范围 0x00=±2g;0x08=±4g;0x10=±8g;0x18=±16g;
    iic_sent_add(MPU6050_DEV_ADDR, User_Control, 0x00);
    iic_sent_add(MPU6050_DEV_ADDR, INT_PIN_CFG, 0x02);
}

/**********************************************************************
获取MPU6050值
例：angle_x = mpu6050_getdata(ACCEL_XOUT_H);//获取X方向加速度分量
 **********************************************************************/
int16 mpu6050_getdata(uint8 reg)
{
    uint8 h, l;
    h = iic_read_add(MPU6050_DEV_ADDR, reg);
    l = iic_read_add(MPU6050_DEV_ADDR, reg + 1);
    return (h << 8) | l;
}

/**********************************************************************
vl53l0红外测距模块初始化
前提IIC初始化成功
 **********************************************************************/
void vl53l0_init()
{
}

/**********************************************************************
获取vl53l0红外测距模块值
val=vl53l0_getdata(VL53L0_REG)
 **********************************************************************/
uint16 vl53l0_getdata(uint8 reg)
{
    uint8 h, l;
    uint16 data_vl53;

    iic_sent_add(VL53L0_DEV_ADDR, 0x00, 1);

    h = iic_read_add(VL53L0_DEV_ADDR, reg);
    l = iic_read_add(VL53L0_DEV_ADDR, reg + 1);
    data_vl53 = (h << 8) | l;
    return data_vl53;
}